Skip to content

feat(config): extensions section, capabilities bindings, and config-level validation#2538

Merged
jmacd merged 6 commits intoopen-telemetry:mainfrom
gouslu:gouslu/extension-system-pr1-config
Apr 9, 2026
Merged

feat(config): extensions section, capabilities bindings, and config-level validation#2538
jmacd merged 6 commits intoopen-telemetry:mainfrom
gouslu:gouslu/extension-system-pr1-config

Conversation

@gouslu
Copy link
Copy Markdown
Contributor

@gouslu gouslu commented Apr 3, 2026

Change Summary

This is PR 1 based on #2510.

Add config parsing for pipeline extensions — the first building block of the extension system (architecture doc).

Extensions are standalone pipeline components that provide shared capabilities (auth, storage, etc.) to data-path nodes. This PR adds config-level support only — no runtime behavior. Extensions are parsed and validated but not created or started.

Config changes:

  • extensions: section in pipeline config, separate from nodes:
  • capabilities: field on nodes for binding capabilities to extension instances
  • NodeKind::Extension variant for URN parsing (e.g., urn:otel:extension:auth)
  • ExtensionConfig struct in engine config
  • PipelineConfigBuilder::add_extension() for programmatic config construction

Validations added:

  • Capability bindings must reference extensions that exist in the extensions: section
  • Extensions cannot have capabilities: bindings (they provide capabilities, not consume them)
  • Extension URN in nodes: section → ExtensionInNodesSection error
  • extensions: at group level rejected by serde (deny_unknown_fields)
  • Duplicate names across nodes and extensions rejected

Example config:

extensions:
  azure_auth:
    type: "urn:microsoft:extension:azure_identity_auth"
    config:
      method: "managed_identity"

nodes:
  exporter:
    type: "urn:microsoft:exporter:azure_monitor"
    capabilities:
      bearer_token_provider: "azure_auth"

What issue does this PR close?

  • Part of the extension system initiative (Phase 1, PR 1 of 8)

How are these changes tested?

13 new config tests covering:

  • Extensions parsed separately from nodes
  • Extension with config and capability bindings
  • Extension URN kind detection
  • Duplicate extension/node name rejection
  • Extension URN in nodes section detection
  • Non-extension URN in extensions section detection
  • Empty/missing extensions section
  • Empty capabilities
  • Multiple extensions with capability bindings
  • Capability binding to nonexistent extension (rejected)
  • Capability binding to existing extension (passes)
  • Capabilities on extension itself (rejected)
  • Extensions at group level (rejected by serde)

All 168 config tests pass. Example config YAML added to configs/.

Are there any user-facing changes?

Yes — pipeline YAML configs now support extensions: and capabilities: sections. These are optional and have no runtime effect in this PR.

@gouslu gouslu requested a review from a team as a code owner April 3, 2026 21:04
@github-actions github-actions bot added the rust Pull requests that update Rust code label Apr 3, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 3, 2026

Codecov Report

❌ Patch coverage is 92.64706% with 35 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.38%. Comparing base (b28727c) to head (3a17f12).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main    #2538    +/-   ##
========================================
  Coverage   88.37%   88.38%            
========================================
  Files         622      622            
  Lines      230058   230531   +473     
========================================
+ Hits       203318   203746   +428     
- Misses      26216    26261    +45     
  Partials      524      524            
Components Coverage Δ
otap-dataflow 90.20% <92.64%> (+<0.01%) ⬆️
query_abstraction 80.61% <ø> (ø)
query_engine 90.74% <ø> (ø)
otel-arrow-go 52.45% <ø> (ø)
quiver 92.27% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@gouslu gouslu force-pushed the gouslu/extension-system-pr1-config branch 2 times, most recently from 4eec6cc to 18e9f65 Compare April 3, 2026 21:42
@gouslu gouslu force-pushed the gouslu/extension-system-pr1-config branch from 18e9f65 to a520a65 Compare April 3, 2026 21:44
@kamilon
Copy link
Copy Markdown
Contributor

kamilon commented Apr 3, 2026

The architecture doc link doesn't work. Can you please fix that? I'd like to understand what this is being built against.

@gouslu gouslu marked this pull request as draft April 3, 2026 23:39
@jmacd jmacd marked this pull request as ready for review April 6, 2026 19:34
@jmacd
Copy link
Copy Markdown
Contributor

jmacd commented Apr 6, 2026

I believe this is ready to review because this PR1 is consistent with the original extensions design document. If there are objections to #2510, let them surface now! I will merge that PR before I merge this one, but both are ready to review.

gouslu added 3 commits April 6, 2026 13:46
- Fixed imports in crates/config/src/node.rs (merged both HEAD and main branches)
- Fixed Extension variant in node.rs match expressions
- Fixed Extension variant in crates/controller/src/startup.rs
- Removed duplicate dead code functions from src/main.rs
- Cleaned up unused imports
- All tests pass, rustfmt formatted, clippy clean
@gouslu gouslu force-pushed the gouslu/extension-system-pr1-config branch from 31e0c61 to f309fd6 Compare April 7, 2026 20:58
skip_serializing_if = "HashMap::is_empty",
deserialize_with = "deserialize_no_dup_keys"
)]
pub capabilities: HashMap<CapabilityId, NodeId>,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This enforces one extension per capability per node. Is this intentional? The design doc doesn't state this explicitly.

If an exporter needs header_setter functionality from two independent extensions (e.g., one for correlation headers, one for custom metadata headers), the only workaround would be for the user to write a custom extension that combines both. That seems like a heavy ask for what might be a common use case.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed this, at some point. I feel that if there are more than one capability, we should follow the Collectr's naming convention and use names like bearer_token/left bearer_token/right if you need more than one. I figure we should tackle this when it happens.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with tackling this later. However, one thing to keep in mind: the design doc states that capabilities are "known by the engine version and validated during configuration loading," and that external extensions cannot introduce new capability interfaces. This is different from the Go Collector, where any extension can expose any interface and components look them up by ID at runtime.

So bearer_token/left and bearer_token/right would each need to be pre-registered as known capabilities in the engine core. It's not purely a user naming convention like it would be in the Go Collector. Each new variant requires an engine core change, so this may not be as straightforward to address when the time comes. Just wanted to flag this so it's not overlooked.

Copy link
Copy Markdown
Contributor Author

@gouslu gouslu Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on how you resolve them. /left and /right might just mean that there are 2 different instances and that you get provided with a map hat has both in it or something like that. What would need to be known is the capability id basically, same as today.

@jmacd jmacd enabled auto-merge April 8, 2026 23:26
@jmacd jmacd added this pull request to the merge queue Apr 8, 2026
Merged via the queue into open-telemetry:main with commit 640e709 Apr 9, 2026
69 of 70 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rust Pull requests that update Rust code

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants